4. Foreign Key Constraints
You can create a foreign key
to enforce a relationship between the data in two tables. Say that you
have an Orders table and an OrderDetails table. When a customer places
an order, you insert one record into Orders. Then, for each line item,
you place a record into OrderDetails. Naturally you would want each line
item in OrderDetails to contain the order number, so that you could
refer to the order record for any given line item. That order number in
OrderDetails is an example of a foreign key. By defining such a
relationship explicitly, you enable SQL Server to ensure that each order
number in the child table OrderDetails represents a valid order in the
parent table Orders.
NOTE
You cannot change a
primary key or unique constraint while it is being referenced by a
foreign key constraint; you have to remove the foreign key first.
To create a foreign key you can use the ALTER TABLE statement. You can use the NO CHECK
option to force the creation of the foreign key, even if the existing
data does not meet the foreign key requirements. All data entered after
the foreign key is created will then be forced comply with the
constraint. Listing 9-15 uses the ALTER TABLE
statement to create a foreign key constraint on the OrderID column in
the OrderDetails table that references the OrderID column in the Orders
table.
You can specify the CASCADE
option to apply any updates or deletes made to the Orders table to the
OrderDetails table. For example, if an order is deleted from the Orders
table, all of the records in the OrderDetails table that reference that
OrderID will be deleted as well.
Example 11. Creating a Foreign Key Constraint Between Two Tables
USE AdventureWorks2008 GO
--Drop the tables if they currently exist IF OBJECT_ID('dbo.OrderDetails', 'U') IS NOT NULL DROP TABLE dbo.OrderDetails;
IF OBJECT_ID('dbo.Orders', 'U') IS NOT NULL DROP TABLE dbo.Orders;
--Create the tables CREATE TABLE Orders (OrderID int NOT NULL CONSTRAINT PK_ORDERS PRIMARY KEY CLUSTERED, OrderNumber int NULL CONSTRAINT UQ_ORDER_NUMBER UNIQUE NONCLUSTERED)
CREATE TABLE OrderDetails (OrderDetailID int IDENTITY (1,1) NOT NULL CONSTRAINT PK_ORDER_DETAILS PRIMARY KEY CLUSTERED, OrderID int NOT NULL, ProductID int NOT NULL)
--Add the foreign key constraint ALTER TABLE OrderDetails WITH NOCHECK ADD CONSTRAINT FK_OrderDetails_Orders FOREIGN KEY(OrderID) REFERENCES Orders (OrderID) ON UPDATE CASCADE ON DELETE CASCADE
|
The script from Listing 11 creates the tables shown in Figure 2 with a one-to-many relationship between the Orders and the OrderDetails tables.
You can disable a foreign key
when you want to perform certain operations, such as inserts and
deletes that the foreign key would cause to fail. Execute the ALTER TABLE statement with the NOCHECK CONSTRAINT keywords followed by the constraint name. Optionally, you can use the ALL keyword to disable all constraints on a table at once. Re-enable the constraints by changing the NOCHECK keyword to CHECK and reissuing the statement. Listing 12 shows the syntax to disable and enable constraints.
NOTE
You can disable only foreign key and check constraints using the NOCHECK keyword. Any other constraints, such as primary key and unique constraints, will still be enabled.
Example 12. Syntax Used to Disable/Enable Constraints
--Disable the FK_OrderDetails_Orders constraint on the OrderDetails table ALTER TABLE OrderDetails NOCHECK CONSTRAINT FK_OrderDetails_Orders
--Disable the all constraints on the OrderDetails table ALTER TABLE OrderDetails NOCHECK CONSTRAINT ALL
--Enable the FK_OrderDetails_Orders constraint on the OrderDetails table ALTER TABLE OrderDetails CHECK CONSTRAINT FK_OrderDetails_Orders
--Enable the all constraints on the OrderDetails table ALTER TABLE OrderDetails CHECK CONSTRAINT ALL
|
To remove a foreign key constraint from a table, issue the ALTER TABLE statement with the DROP CONSTRAINT keywords followed by the name of the foreign key constraint, as shown in Listing 13.
Example 13. Code to Remove a Foreign Key Constraint
ALTER TABLE dbo.OrderDetails DROP CONSTRAINT FK_OrderDetails_Orders